package com.feinno.urcs.group.servlet;

import com.feinno.msrp.MsrpFuture;
import com.feinno.msrp.MsrpFutureListener;
import com.feinno.msrp.MsrpSession;
import com.feinno.msrp.message.MsrpMessage;
import com.feinno.sip.message.SipResponse;
import com.feinno.urcs.content.Sdp;
import com.feinno.urcs.content.UrcsMultipartMimeContent;
import com.feinno.urcs.group.GroupConfiguration;
import com.feinno.urcs.group.api.GroupMessageLogService;
import com.feinno.urcs.sipservlet.SipSession;
import com.feinno.urcs.sipservlet.msrp.MsrpUtils;
import com.feinno.urcs.types.MobileNo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sdp.SdpException;
import javax.sdp.SessionDescription;
import java.net.InetSocketAddress;
import java.net.URI;
import java.text.ParseException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Li.Hongbo <lihongbo@feinno.com>
 */
public abstract class GroupMemberDialog {

	protected int groupId;
	protected MobileNo memberMobile;
	protected GroupServlet servlet;
	protected SipSession sipSession;
	protected MsrpSession msrp;
	protected URI remoteMsrpPath;
	protected URI localMsrpPath;
	protected AtomicBoolean mediaAlready = new AtomicBoolean(false);
	private AtomicBoolean isClean = new AtomicBoolean(false);
	private static final Logger LOGGER = LoggerFactory.getLogger(GroupMemberDialog.class);
	protected GroupMessageLogService logService;

	public GroupMemberDialog(GroupServlet servlet, GroupMessageLogService logService) {
		this.servlet = servlet;
		this.logService = logService;
	}

	/**
	 * 这个地方的逻辑是:
	 * 如果MSRP 没有准备好, 则等待. 并将消息堆积到离线里面,然后继续下面逻辑.
	 * <p>
	 * MSRP 准备好后, 如果有离线,则先吧离线发完, 在发完之前所有新来的消息都往离线里面堆, 直到没有离线了.
	 * 如果离线发送过程中 某一条失败, 则将失败消息的groupMessageID 记录到离线的偏移量中.
	 *
	 * @param referBy
	 * @param contentType
	 * @param content
	 */
	public abstract void sendText(MobileNo referBy, String contentType, long groupMessageStorageId, byte[] content);

	public boolean isClean() {
		return isClean.get();
	}

	public void setClean(boolean clean) {
		isClean.set(clean);
	}

	/**
	 * 作为应答方 等待对端链接
	 *
	 * @param msrp
	 */
	public abstract void initMsrpSession(MsrpSession msrp);

	public int getGroupId() {
		return groupId;
	}

	public void setGroupId(int groupId) {
		this.groupId = groupId;
	}

	public MobileNo getMemberMobile() {
		return memberMobile;
	}

	public void closeDialog() {
		closeSipSession();
		closeMsrp();
	}

	public abstract void closeSipSession();

	public abstract void closeMsrp();

	public SipSession getSipSession() {
		return sipSession;
	}

	public void setSipSession(SipSession sipSession) {
		this.sipSession = sipSession;
	}

	public void setRemoteMsrpPath(URI peerMsrpPath) {
		this.remoteMsrpPath = peerMsrpPath;
	}

	public void setLocalMsrpPathBySDP(SessionDescription sdp) throws SdpException, ParseException {
		localMsrpPath = URI.create(MsrpUtils.getMsrpPath(sdp));
	}

	protected void bindMsrp(SipResponse response) throws SdpException, ParseException {
		UrcsMultipartMimeContent multipartMimeContent = UrcsMultipartMimeContent.newInstance(response.getContentTypeHeader(), response.getRawContent());
		Sdp sdp = multipartMimeContent.getContent(Sdp.class);
		SessionDescription sd = sdp.getSdp();
		boolean isActive = MsrpUtils.isActive(sd);
		remoteMsrpPath = java.net.URI.create(MsrpUtils.getMsrpPath(sd));
		if (!isActive) {
			// 如果对端是ACTIVE，只好由我们主动链接，链接成功后返回200，失败则500
			InetSocketAddress remoteAddress = MsrpUtils.getAddressBySdp(sd);
			MsrpFuture msrpFuture = msrp.alive(remoteAddress.getHostString(), remoteAddress.getPort(), remoteMsrpPath);
			msrpFuture.addListener(new MsrpFutureListener() {
				@Override
				public void sendSuccess(MsrpMessage msrpMessage) {
					mediaAlready.set(true);
				}

				@Override
				public void sendFailed(MsrpMessage msrpMessage, Throwable throwable) {
					mediaAlready.set(false);
					LOGGER.error("bindMsrp  MsrpFutureListener", throwable);
				}
			});
		} else {
			// 如果是对端主动链接，并且空包已经过来了，则回复本次邀请200
		}
	}

	public void setMemberMobile(MobileNo memberMobile) {
		this.memberMobile = memberMobile;
	}

	public GroupServlet getServlet() {
		return servlet;
	}

	public void setServlet(GroupServlet servlet) {
		this.servlet = servlet;
	}

	public MsrpSession getMsrp() {
		return msrp;
	}

	public void setMsrp(MsrpSession msrp) {
		this.msrp = msrp;
	}

	public URI getRemoteMsrpPath() {
		return remoteMsrpPath;
	}

	public URI getLocalMsrpPath() {
		return localMsrpPath;
	}

	public void setLocalMsrpPath(URI localMsrpPath) {
		this.localMsrpPath = localMsrpPath;
	}

	public AtomicBoolean getMediaAlready() {
		return mediaAlready;
	}

	public void setMediaAlready(AtomicBoolean mediaAlready) {
		this.mediaAlready = mediaAlready;
	}

	public abstract void hadMoreMessage();

	public abstract void cancel();

	public String getGroupUriByGrouupId() {
		StringBuilder sb = new StringBuilder();
		sb.append("sip:");
		sb.append(GroupConfiguration.INSTANCE.getGroupPrefix());
		sb.append(getGroupId());
		sb.append("@");
		sb.append(GroupConfiguration.INSTANCE.getGroupDomain());
		return sb.toString();
	}


}
